#include "../header/building.h"
#include "../header/shape.h"

// ============================================== //
// ================== BUILDING ================== //
// ============================================== //

void Building::Toiture(const Vector& a, const Vector& b, const Vector& c, const Vector& d)
{
	Vector A = Vector(a[0], a[1], a[2]);
	Vector B = Vector(b[0], b[1], b[2]);
	Vector C = Vector(c[0], c[1], c[2]);
	Vector D = Vector(d[0], d[1], d[2]);

	Quadrangle q =  Quadrangle(A, B, C, D).Shrink(0.1, 0.1, 0.1, 0.1);
	Vector AP = q[0], BP = q[1], CP = q[2], DP = q[3];

	PrismQuad(A, B, BP, AP, 0.2).Render();
	PrismQuad(C, D, DP, CP, 0.2).Render();
	PrismQuad(B, C, CP, BP, 0.2).Render();
	PrismQuad(D, A, AP, DP, 0.2).Render();
}

void Building::Specialization()
{
	RandFloor();
	Vector a = p[0], b = p[1], c = p[2], d = p[3];
	Vector aP = p[0], bP = p[1], cP = p[2], dP = p[3];

	aP[2] = 0.3 * floor;
	bP[2] = 0.3 * floor;
	cP[2] = 0.3 * floor;
	dP[2] = 0.3 * floor;

	Quadrangle q = Quadrangle(a, b, c, d);
	int R = rand() % 100;

	Quadrangle qp = q.Shrink(0, 0, 0, 0);

	Vector A = qp[0], B = qp[1], C = qp[2], D = qp[3];

	double max2 = std::max(std::max(std::max(Norm(b - a), Norm(b - c)), Norm(c - d)), Norm(d - a));
	double Min2 = std::min(std::min(std::min(Norm(b - a), Norm(b - c)), Norm(c - d)), Norm(d - a));
	//PrismQuad(A,B,C,D,floor*0.3).Render();

	if(R < 30)
		ClassicBuild(A, B, C, D, floor).GroundFloor();
	else if(R >=  30 && R <=  31)
		Church(A, B, C, D, floor).GroundFloor();
	else if(R > 32 && R < 50)
		GlassBuild(A, B, C, D, floor).GroundFloor();
	else if(R >= 50)
		School(A, B, C, D, floor).GroundFloor();
}

void Building::Subdivide()
{
		Specialization();

}

void Building::RandFloor()
{
	double x = (p[0][0] + p[1][0] + p[2][0] + p[3][0]) / 4;
	double y = (p[0][1] + p[1][1] + p[2][1] + p[3][1]) / 4;

	if((x >  - 5 && x < 5) && (y >  - 5 && y < 5))
		floor = 10 + (rand() % (15 - 10));
	else
		if(((y <  - 5 || y < 5) &&(x >  - 5 || x < 5)) ||
			((y >  - 5 || y > 5) &&(x <  - 5 || x > 5)))
			floor = 6 + (rand() % (10 - 6));
		else
			floor = 3 + (rand() % (6 - 3));
}

// ============================================== //
// =============== CLASSIC BUILD ================ //
// ============================================== //

void ClassicBuild::GroundFloor()
{
	Quadrangle wall1 = Quadrangle(p[0], p[1], p[2], p[3]).Shrink(0.01, 0.01, 0.01, 0.01);
	Quadrangle wall22 = Quadrangle(p[0], p[1], p[2], p[3]).Shrink(0.015, 0.015, 0.015, 0.015);
	
	Vector a = p[0], b = p[1], c = p[2], d = p[3];
	Vector aP = wall1[0], bP = wall1[1], cP = wall1[2], dP = wall1[3];
	Vector aS = wall22[0], bS = wall22[1], cS = wall22[2], dS = wall22[3];
	Vector A = a, C = c, D = d, B = b, AP = aP, BP = bP, CP = cP, DP = dP, AS = aS, BS = bS, CS = cS, DS = dS;

	double max = std::max(std::max(std::max(Norm(p[1] - p[0]), Norm(p[1] - p[2])), Norm(p[2] - p[3])), Norm(p[3] - p[0]));

	if(max  ==  Norm(p[1] - p[0]) || max  ==  Norm(p[3] - p[2]))
	{
		FirstFront(a, b, bP, aP);
		FirstFront(c, d, dP, cP);
		SecondFront(b, c, cS, bS);
		SecondFront(d, a, aS, dS);

		for(int i = 1; i < floor ; i++)
		{
			A[2] = A[2] + 0.3, B[2] = B[2] + 0.3, C[2] = C[2] + 0.3, D[2] = D[2] + 0.3, 
			AP[2] = AP[2] + 0.3, BP[2] = BP[2] + 0.3, CP[2] = CP[2] + 0.3, DP[2] = DP[2] + 0.3, 
			AS[2] = AS[2] + 0.3, BS[2] = BS[2] + 0.3, CS[2] = CS[2] + 0.3, DS[2] = DS[2] + 0.3;

			FirstWindow(A, B, BP, AP);
			FirstWindow(C, D, DP, CP);
			FirstWindow(B, C, CS, BS);
			FirstWindow(D, A, AS, DS);

			PrismQuad(A, B, C, D, 0.03).Render();
		}
	}
	else
	{
		FirstFront(d, a, aS, dS);
		FirstFront(b, c, cP, bP);
		SecondFront(c, d, dP, cP);
		SecondFront(a, b, bS, aS);

		for(int i = 1; i < floor; i++)
		{
			A[2] = A[2] + 0.3, B[2] = B[2] + 0.3, C[2] = C[2] + 0.3, D[2] = D[2] + 0.3, 
			AP[2] = AP[2] + 0.3, BP[2] = BP[2] + 0.3, CP[2] = CP[2] + 0.3, DP[2] = DP[2] + 0.3, 
			AS[2] = AS[2] + 0.3, BS[2] = BS[2] + 0.3, CS[2] = CS[2] + 0.3, DS[2] = DS[2] + 0.3;

			FirstWindow(D, A, AS, DS);
			FirstWindow(B, C, CP, BP);
			FirstWindow(C, D, DP, CP);
			FirstWindow(A, B, BS, AS);

			PrismQuad(A, B, C, D, 0.03).Render();
		}
	}

	A[2] = A[2] + 0.3, B[2] = B[2] + 0.3, C[2] = C[2] + 0.3, D[2] = D[2] + 0.3;
	Toit(A, B, C, D, 0.01).Render();
}


void ClassicBuild::FirstFront(const Vector& a, const Vector& b, const Vector& c, const Vector& d)
{
   // FACADE EXTERIEUR
	double Xf1 = a[0] + (b[0] - a[0]) * 1 / 7;
	double Yf1 = a[1] + (b[1] - a[1]) * 1 / 7;
	Vector F1 = Vector (Xf1, Yf1, 0);

	double Xf2 = a[0] + (b[0] - a[0]) * 2 / 7;
	double Yf2 = a[1] + (b[1] - a[1]) * 2 / 7;
	Vector F2 = Vector (Xf2, Yf2, 0);

	double Xp1 = a[0] + (b[0] - a[0]) * 3 / 7;
	double Yp1 = a[1] + (b[1] - a[1]) * 3 / 7;
	Vector P1 = Vector (Xp1, Yp1, 0);

	double Xp2 = a[0] + (b[0] - a[0]) * 4 / 7;
	double Yp2 = a[1] + (b[1] - a[1]) * 4 / 7;
	Vector P2 = Vector (Xp2, Yp2, 0);

	double Xf3 = a[0] + (b[0] - a[0]) * 5 / 7;
	double Yf3 = a[1] + (b[1] - a[1]) * 5 / 7;
	Vector F3 = Vector (Xf3, Yf3, 0);

	double Xf4 = a[0] + (b[0] - a[0]) * 5 / 7;
	double Yf4 = a[1] + (b[1] - a[1]) * 5 / 7;
	Vector F4 = Vector (Xf4, Yf4, 0);

	// FACADE INTERIEUR
	double Xf1S = d[0] + (c[0] - d[0]) * 1 / 7;
	double Yf1S = d[1] + (c[1] - d[1]) * 1 / 7;
	Vector F1S = Vector (Xf1S, Yf1S, 0);

	double Xf2S = d[0] + (c[0] - d[0]) * 2 / 7;
	double Yf2S = d[1] + (c[1] - d[1]) * 2 / 7;
	Vector F2S = Vector (Xf2S, Yf2S, 0);

	double Xp1S = d[0] + (c[0] - d[0]) * 3 / 7;
	double Yp1S = d[1] + (c[1] - d[1]) * 3 / 7;
	Vector P1S = Vector (Xp1S, Yp1S, 0);

	double Xp2S = d[0] + (c[0] - d[0]) * 4 / 7;
	double Yp2S = d[1] + (c[1] - d[1]) * 4 / 7;
	Vector P2S = Vector (Xp2S, Yp2S, 0);

	double Xf3S = d[0] + (c[0] - d[0]) * 5 / 7;
	double Yf3S = d[1] + (c[1] - d[1]) * 5 / 7;
	Vector F3S = Vector (Xf3S, Yf3S, 0);

	double Xf4S = d[0] + (c[0] - d[0]) * 6 / 7;
	double Yf4S = d[1] + (c[1] - d[1]) * 6 / 7;
	Vector F4S = Vector (Xf4S, Yf4S, 0);

	PrismQuad(a, F1, F1S, d , 0.3).Render();
	PrismQuad(F2, P1, P1S, F2S, 0.3).Render();
	PrismQuad(P2, F3, F3S, P2S, 0.3).Render();
	PrismQuad(F4, b, c, F4S, 0.3).Render();
}

void ClassicBuild::SecondFront(const Vector& a, const Vector& b, const Vector& c, const Vector& d)
{
        double X1 = a[0] + (b[0] - a[0]) * 3 / 7;
		double Y1 = a[1] + (b[1] - a[1]) * 3 / 7;
		Vector p1 = Vector (X1, Y1, 0);

		double X2 = a[0] + (b[0] - a[0]) * 3 / 7;
		double Y2 = a[1] + (b[1] - a[1]) * 3 / 7;
		Vector p2 = Vector (X2, Y2, 0);

		double X1s = d[0] + (c[0] - d[0]) * 4 / 7;
		double Y1s = d[1] + (c[1] - d[1]) * 4 / 7;
		Vector p1S = Vector (X1s, Y1s, 0);

		double X2s = d[0] + (c[0] - d[0]) * 4 / 7;
		double Y2s = d[1] + (c[1] - d[1]) * 4 / 7;
		Vector p2S = Vector (X2s, Y2s, 0);

	    PrismQuad(a, p1, p1S, d, 0.3).Render();
		PrismQuad(p2, b, c, p2S, 0.3).Render();
}

void ClassicBuild::FirstWindow(const Vector& a, const Vector& b, const Vector& c, const Vector& d)
{
	double max = std::max(std::max(std::max(Norm(b - a), Norm(b - c)), Norm(c - d)), Norm(d - a));
	if(max >= 0.6)
	{
		double Xab = a[0] + (b[0] - a[0]) / 2;
		double Yab = a[1] + (b[1] - a[1]) / 2;
		Vector AB = Vector (Xab, Yab, a[2]);

		double Xcd = d[0] + (c[0] - d[0]) / 2;
		double Ycd = d[1] + (c[1] - d[1]) / 2;
		Vector CD = Vector (Xcd, Ycd, c[2]);

		FirstWindow(a, AB, CD, d);
		FirstWindow(AB, b, c, CD);
	}
	else
	{
		double Xab1 = a[0] + (b[0] - a[0]) / 3;
		double Yab1 = a[1] + (b[1] - a[1]) / 3;
		Vector AB1 = Vector (Xab1, Yab1, a[2] + 0.1);
		Vector AB1P = Vector (Xab1, Yab1, a[2] + 0.25);

		double Xab2 = a[0] + (b[0] - a[0]) * 2 / 3;
		double Yab2 = a[1] + (b[1] - a[1]) * 2 / 3;
		Vector AB2 = Vector (Xab2, Yab2, a[2] + 0.1);
		Vector AB2P = Vector (Xab2, Yab2, a[2] + 0.25);

		double Xcd1 = d[0] + (c[0] - d[0]) / 3;
		double Ycd1 = d[1] + (c[1] - d[1]) / 3;
		Vector CD1 = Vector (Xcd1, Ycd1, d[2] + 0.1);
		Vector CD1P = Vector (Xcd1, Ycd1, d[2] + 0.25);

		double Xcd2 = d[0] + (c[0] - d[0]) * 2 / 3;
		double Ycd2 = d[1] + (c[1] - d[1]) * 2 / 3;
		Vector CD2 = Vector (Xcd2, Ycd2, d[2] + 0.1);
		Vector CD2P = Vector (Xcd2, Ycd2, d[2] + 0.25);

		Vector ap = a, cp = c, dp = d, bp = b;
		ap[2] = ap[2] + 0.1, bp[2] = bp[2] + 0.1, cp[2] = cp[2] + 0.1, dp[2] = dp[2] + 0.1;

		Vector as = a, cs = c, ds = d, bs = b;
		as[2] = a[2] + 0.25, bs[2] = b[2] + 0.25, cs[2] = c[2] + 0.25, ds[2] = d[2] + 0.25;

		PrismQuad(a, b, c, d, 0.1).Render();
		PrismQuad(ap, AB1, CD1, dp, 0.15).Render();
		PrismQuad(AB2, bp, cp, CD2, 0.15).Render();
		PrismQuad(as, bs, cs, ds, 0.05).Render();
	}
}


// ============================================== //
// =================== CHURCH =================== //
// ============================================== //

void Church ::GroundFloor()
{
	Quadrangle wall1 = Quadrangle(p[0], p[1], p[2], p[3]).Shrink(0.01, 0.01, 0.01, 0.01);
	Quadrangle wall2 = Quadrangle(p[0], p[1], p[2], p[3]).Shrink(0.015, 0.015, 0.015, 0.015);
	
	Vector a = p[0], b = p[1], c = p[2], d = p[3];
	Vector aP = wall1[0], bP = wall1[1], cP = wall1[2], dP = wall1[3];
	Vector aS = wall2[0], bS = wall2[1], cS = wall2[2], dS = wall2[3];

	Vector A = a, C = c, D = d, B = b, AP = aP, BP = bP, CP = cP, DP = dP, AS = aS, BS = bS, CS = cS, DS = dS;
	Quadrangle steeple;

	double max = std::max(std::max(std::max(Norm(p[1] - p[0]), Norm(p[1] - p[2])), Norm(p[2] - p[3])), Norm(p[3] - p[0]));

	if(max  ==  Norm(p[1] - p[0]) || max  ==  Norm(p[3] - p[2]))
	{
		SecondFront(a, b, bP, aP);
		SecondFront(c, d, dP, cP);
		SecondFront(b, c, cS, bS);
		FirstFront(d, a, aS, dS);

		steeple = Quadrangle(p[0], p[1], p[2], p[3]).Shrink(0, 1, 1, 0);
	}
	else
	{
		SecondFront(d, a, aS, dS);
		SecondFront(b, c, cP, bP);
		SecondFront(c, d, dP, cP);
		FirstFront(a, b, bS, aS);

		steeple = Quadrangle(p[0], p[1], p[2], p[3]).Shrink(0, 0, 1, 1);
	}
	
	if(steeple.Area() > 4)
	{
		PrismQuad(steeple, 2).Render();
		Vector t1 = steeple[0], t2 = steeple[1], t3 = steeple[2], t4 = steeple[3];
		t1[2] = 2, t2[2] = 2, t3[2] = 2, t4[2] = 2;
		Toit(t1, t2, t3, t4, 0.5).Render();
	}

	Vector as = a, bs = b, cs = c, ds = d;
	as[2] = 0.6, bs[2] = 0.6, cs[2] = 0.6, ds[2] = 0.6;
	Toit2(as, bs, cs, ds, 0.3).Render();
}

void Church::FirstFront(const Vector& a, const Vector& b, const Vector& c, const Vector& d)
{
	// FACADE EXTERIEUR
	double Xp1 = a[0] + (b[0] - a[0]) * 1 / 3;
	double Yp1 = a[1] + (b[1] - a[1]) * 1 / 3;
	Vector P1 = Vector (Xp1, Yp1, 0);
	Vector P1T = Vector (Xp1, Yp1, 0.2);

	double Xp2 = a[0] + (b[0] - a[0]) * 2 / 3;
	double Yp2 = a[1] + (b[1] - a[1]) * 2 / 3;
	Vector P2 = Vector (Xp2, Yp2, 0);
	Vector P2T = Vector (Xp2, Yp2, 0.2);

	// FACADE INTERIEUR
	double Xp1S = d[0] + (c[0] - d[0]) * 1 / 3;
	double Yp1S = d[1] + (c[1] - d[1]) * 1 / 3;
	Vector P1S = Vector (Xp1S, Yp1S, 0);
	Vector P1ST = Vector (Xp1S, Yp1S, 0.3);

	double Xp2S = d[0] + (c[0] - d[0]) * 2 / 3;
	double Yp2S = d[1] + (c[1] - d[1]) * 2 / 3;
	Vector P2S = Vector (Xp2S, Yp2S, 0);
	Vector P2ST = Vector (Xp2S, Yp2S, 0.3);

	PrismQuad(a, P1, P1S, d, 0.3).Render();
	PrismQuad(P2, b, c, P2, 0.3).Render();
	PrismQuad(P1T, P2T, P2ST, P1ST, 0.3).Render();
	 
}

// ============================================== //
// =================== SCHOOL =================== //
// ============================================== //

void School::GroundFloor()
{
	Quadrangle wall1 = Quadrangle(p[0], p[1], p[2], p[3]).Shrink(0.01, 0.01, 0.01, 0.01);
	Quadrangle wall2 = Quadrangle(p[0], p[1], p[2], p[3]).Shrink(0.015, 0.015, 0.015, 0.015);
	
	Vector a = p[0], b = p[1], c = p[2], d = p[3];
	Vector aP = wall1[0], bP = wall1[1], cP = wall1[2], dP = wall1[3];
	Vector aS = wall2[0], bS = wall2[1], cS = wall2[2], dS = wall2[3];

	Vector A = a, C = c, D = d, B = b, AP = aP, BP = bP, CP = cP, DP = dP, AS = aS, BS = bS, CS = cS, DS = dS;
	double max = std::max(std::max(std::max(Norm(p[1] - p[0]), Norm(p[1] - p[2])), Norm(p[2] - p[3])), Norm(p[3] - p[0]));

	if(max == Norm(p[1] - p[0]) || max == Norm(p[3] - p[2]))
	{
		FirstFront(a, b, bP, aP);
		FirstFront(c, d, dP, cP);
		SecondFront(b, c, cS, bS);
		SecondFront(d, a, aS, dS);

		for(int i = 1; i < 2; i++)
		{
			A[2] =  A[2] + 0.3, B[2] = B[2] + 0.3, C[2] = C[2] + 0.3, D[2] = D[2] + 0.3, 
			AP[2] = AP[2] + 0.3, BP[2] = BP[2] + 0.3, CP[2] = CP[2] + 0.3, DP[2] = DP[2] + 0.3, 
			AS[2] = AS[2] + 0.3, BS[2] = BS[2] + 0.3, CS[2] = CS[2] + 0.3, DS[2] = DS[2] + 0.3;

			FirstWindow(A, B, BP, AP);
			FirstWindow(C, D, DP, CP);
			FirstWindow(B, C, CS, BS);
			FirstWindow(D, A, AS, DS);

			PrismQuad(A, B, C, D, 0.01).Render();
		}
	}
	else
	{
		FirstFront(d, a, aS, dS);
		FirstFront(b, c, cP, bP);
		SecondFront(c, d, dP, cP);
		SecondFront(a, b, bS, aS);

		for(int i = 1; i < 2; i++)
		{
			A[2] =  A[2] + 0.3, B[2] = B[2] + 0.3, C[2] = C[2] + 0.3, D[2] = D[2] + 0.3, 
			AP[2] = AP[2] + 0.3, BP[2] = BP[2] + 0.3, CP[2] = CP[2] + 0.3, DP[2] = DP[2] + 0.3, 
			AS[2] = AS[2] + 0.3, BS[2] = BS[2] + 0.3, CS[2] = CS[2] + 0.3, DS[2] = DS[2] + 0.3;

			FirstWindow(D, A, AS, DS);
			FirstWindow(B, C, CP, BP);
			FirstWindow(C, D, DP, CP);
			FirstWindow(A, B, BS, AS);
			PrismQuad(A, B, C, D, 0.01).Render();
		}
	}

	A[2] =  A[2] + 0.3, B[2] = B[2] + 0.3, C[2] = C[2] + 0.3, D[2] = D[2] + 0.3, 
	Toit(A, B, C, D, 0.01).Render();
}

void School::FirstFront(const Vector& a, const Vector& b, const Vector& c, const Vector& d)
{
	// FACADE EXTERIEUR
	double Xf1 = a[0] + (b[0] - a[0]) * 1 / 7;
	double Yf1 = a[1] + (b[1] - a[1]) * 1 / 7;
	Vector F1 = Vector (Xf1, Yf1, 0);

	double Xf2 = a[0] + (b[0] - a[0]) * 2 / 7;
	double Yf2 = a[1] + (b[1] - a[1]) * 2 / 7;
	Vector F2 = Vector (Xf2, Yf2, 0);

	double Xp1 = a[0] + (b[0] - a[0]) * 3 / 7;
	double Yp1 = a[1] + (b[1] - a[1]) * 3 / 7;
	Vector P1 = Vector (Xp1, Yp1, 0);

	double Xp2 = a[0] + (b[0] - a[0]) * 4 / 7;
	double Yp2 = a[1] + (b[1] - a[1]) * 4 / 7;
	Vector P2 = Vector (Xp2, Yp2, 0);

	double Xf3 = a[0] + (b[0] - a[0]) * 5 / 7;
	double Yf3 = a[1] + (b[1] - a[1]) * 5 / 7;
	Vector F3 = Vector (Xf3, Yf3, 0);

	double Xf4 = a[0] + (b[0] - a[0]) * 6 / 7;
	double Yf4 = a[1] + (b[1] - a[1]) * 6 / 7;
	Vector F4 = Vector (Xf4, Yf4, 0);

	// FACADE INTERIEUR
	double Xf1S = d[0] + (c[0] - d[0]) * 1 / 7;
	double Yf1S = d[1] + (c[1] - d[1]) * 1 / 7;
	Vector F1S = Vector (Xf1S, Yf1S, 0);

	double Xf2S = d[0] + (c[0] - d[0]) * 2 / 7;
	double Yf2S = d[1] + (c[1] - d[1]) * 2 / 7;
	Vector F2S = Vector (Xf2S, Yf2S, 0);

	double Xp1S = d[0] + (c[0] - d[0]) * 3 / 7;
	double Yp1S = d[1] + (c[1] - d[1]) * 3 / 7;
	Vector P1S = Vector (Xf1S, Yf1S, 0);

	double Xp2S = d[0] + (c[0] - d[0]) * 4 / 7;
	double Yp2S = d[1] + (c[1] - d[1]) * 4 / 7;
	Vector P2S = Vector (Xp2S, Yp2S, 0);

	double Xf3S = d[0] + (c[0] - d[0]) * 5 / 7;
	double Yf3S = d[1] + (c[1] - d[1]) * 5 / 7;
	Vector F3S = Vector (Xf3S, Yf3S, 0);

	double Xf4S = d[0] + (c[0] - d[0]) * 6 / 7;
	double Yf4S = d[1] + (c[1] - d[1]) * 6 / 7;
	Vector F4S = Vector (Xf4S, Yf4S, 0);

	PrismQuad(a, F1, F1S, d, 0.3).Render();
	PrismQuad(F2, P1, P1S, F2S, 0.3).Render();
	PrismQuad(P2, F3, F3S, P2S, 0.3).Render();
	PrismQuad(F4, b, c, F4S, 0.3).Render();
}

void School::SecondFront(const Vector& a, const Vector& b, const Vector& c, const Vector& d)
{
	double X1 = a[0] + (b[0] - a[0]) * 3 / 7;
	double Y1 = a[1] + (b[1] - a[1]) * 3 / 7;
	Vector p1 = Vector (X1, Y1, 0);

	double X2 = a[0] + (b[0] - a[0]) * 3 / 7;
	double Y2 = a[1] + (b[1] - a[1]) * 3 / 7;
	Vector p2 = Vector (X2, Y2, 0);

	double X1s = d[0] + (c[0] - d[0]) * 4 / 7;
	double Y1s = d[1] + (c[1] - d[1]) * 4 / 7;
	Vector p1S = Vector (X1s, Y1s, 0);

	double X2s = d[0] + (c[0] - d[0]) * 4 / 7;
	double Y2s = d[1] + (c[1] - d[1]) * 4 / 7;
	Vector p2S = Vector (X2s, Y2s, 0);

	PrismQuad(a, p1, p1S, d, 0.3).Render();
	PrismQuad(p2, b, c, p2S, 0.3).Render();
}

void School :: FirstWindow(const Vector& a, const Vector& b, const Vector& c, const Vector& d)
{
	double max = std::max(std::max(std::max(Norm(b - a), Norm(b - c)), Norm(c - d)), Norm(d - a));

	if(max >=  0.9)
	{
		double Xab = a[0] + (b[0] - a[0]) / 2;
		double Yab = a[1] + (b[1] - a[1]) / 2;
		Vector AB = Vector (Xab, Yab, a[2]);

		double Xcd = d[0] + (c[0] - d[0]) / 2;
		double Ycd = d[1] + (c[1] - d[1]) / 2;
		Vector CD = Vector (Xcd, Ycd, c[2]);

		FirstWindow(a, AB, CD, d);
		FirstWindow(AB, b, c, CD);
	}
	else
	{
		double Xab1 = a[0] + (b[0] - a[0])/3;
		double Yab1 = a[1] + (b[1] - a[1])/3;
		Vector AB1 = Vector (Xab1, Yab1, a[2] + 0.1);
		Vector AB1P = Vector (Xab1, Yab1, a[2] + 0.25);

		double Xab2 = a[0] + (b[0] - a[0]) * 2 / 3;
		double Yab2 = a[1] + (b[1] - a[1]) * 2 / 3;
		Vector AB2 = Vector (Xab2, Yab2, a[2] + 0.1);
		Vector AB2P = Vector (Xab2, Yab2, a[2] + 0.25);


		double Xcd1 = d[0] + (c[0] - d[0]) / 3;
		double Ycd1 = d[1] + (c[1] - d[1]) / 3;
		Vector CD1 = Vector (Xcd1, Ycd1, d[2] + 0.1);
		Vector CD1P = Vector (Xcd1, Ycd1, d[2] + 0.25);

		double Xcd2 = d[0] + (c[0] - d[0]) * 2 / 3;
		double Ycd2 = d[1] + (c[1] - d[1]) * 2 / 3;
		Vector CD2 = Vector (Xcd2, Ycd2, d[2] + 0.1);
		Vector CD2P = Vector (Xcd2, Ycd2, d[2] + 0.25);

		Vector ap = a, cp = c, dp = d, bp = b;
		ap[2] = ap[2] + 0.1, bp[2] = bp[2] + 0.1, cp[2] = cp[2] + 0.1, dp[2] = dp[2] + 0.1;

		Vector as = a, cs = c, ds = d, bs = b;
		as[2] = a[2] + 0.25, bs[2] = b[2] + 0.25, cs[2] = c[2] + 0.25, ds[2] = d[2] + 0.25;

		PrismQuad(a, b, c, d, 0.1).Render();
		PrismQuad(ap, AB1, CD1, dp, 0.15).Render();
		PrismQuad(AB2, bp, cp, CD2, 0.15).Render();
		PrismQuad(as, bs, cs, ds, 0.05).Render();
		//PrismQuad(a, b, c, d, 0.5).Render();
	}
}


// ============================================== //
// ================ GLASS BUILD ================= //
// ============================================== //

void GlassBuild ::GroundFloor()
{
	Quadrangle wall1 = Quadrangle(p[0], p[1], p[2], p[3]).Shrink(0.01, 0.01, 0.01, 0.01);
	Quadrangle wall2 = Quadrangle(p[0], p[1], p[2], p[3]).Shrink(0.015, 0.015, 0.015, 0.015);
	
	Vector a = p[0], b = p[1], c = p[2], d = p[3];
	Vector aP = wall1[0], bP = wall1[1], cP = wall1[2], dP = wall1[3];
	Vector aS = wall2[0], bS = wall2[1], cS = wall2[2], dS = wall2[3];

	Vector A = a, C = c, D = d, B = b, AP = aP, BP = bP, CP = cP, DP = dP, AS = aS, BS = bS, CS = cS, DS = dS;
	double max = std::max(std::max(std::max(Norm(p[1] - p[0]), Norm(p[1] - p[2])), Norm(p[2] - p[3])), Norm(p[3] - p[0]));

	FirstFront(a, b, bP, aP);
	FirstFront(c, d, dP, cP);
	FirstFront(b, c, cS, bS);
	FirstFront(d, a, aS, dS);

	for(int i = 1; i < floor; i++)
	{
		A[2] =  A[2] + 0.25, B[2] = B[2] + 0.25, C[2] = C[2] + 0.25, D[2] = D[2] + 0.25, 
		AP[2] = AP[2] + 0.25, BP[2] = BP[2] + 0.25, CP[2] = CP[2] + 0.25, DP[2] = DP[2] + 0.25, 
		AS[2] = AS[2] + 0.25, BS[2] = BS[2] + 0.25, CS[2] = CS[2] + 0.25, DS[2] = DS[2] + 0.25;

		FirstFront(A, B, BP, AP);
		FirstFront(C, D, DP, CP);
		FirstFront(B, C, CS, BS);
		FirstFront(D, A, AS, DS);

		PrismQuad(A, B, C, D, 0.01).Render();
	}

	A[2] =  A[2] + 0.26, B[2] = B[2] + 0.26, C[2] = C[2] + 0.26, D[2] = D[2] + 0.26;
	Toit2(A, B, C, D, 0.25).Render();
}

void GlassBuild::FirstFront(const Vector& a, const Vector& b, const Vector& c, const Vector& d)
{
	// FACADE EXTERIEUR
	double Xf1 = a[0] + (b[0] - a[0]) * 1 / 10;
	double Yf1 = a[1] + (b[1] - a[1]) * 1 / 10;
	Vector F1 = Vector (Xf1, Yf1, 0.02 + a[2]);

	double Xf2 = a[0] + (b[0] - a[0]) * 9 / 10;
	double Yf2 = a[1] + (b[1] - a[1]) * 9 / 10;
	Vector F2 = Vector (Xf2, Yf2, 0.02 + a[2]);

	// FACADE INTERIEUR
	double Xf1S = d[0] + (c[0] - d[0]) * 1 / 10;
	double Yf1S = d[1] + (c[1] - d[1]) * 1 / 10;
	Vector F1S = Vector (Xf1S, Yf1S, 0.02 + d[2]);

	double Xf2S = d[0] + (c[0] - d[0]) * 9 / 10;
	double Yf2S = d[1] + (c[1] - d[1]) * 9 / 10;
	Vector F2S = Vector (Xf2S, Yf2S, 0.02 + d[2]);

	Vector A1 = Vector (a[0], a[1], a[2] + 0.02);
	Vector A2 = Vector (d[0], d[1], d[2] + 0.02);
	Vector B1 = Vector (b[0], b[1], b[2] + 0.02);
	Vector B2 = Vector (c[0], c[1], c[2] + 0.02);

	Vector A3 = Vector (a[0], a[1], a[2] + 0.22);
	Vector A4 = Vector (d[0], d[1], d[2] + 0.22);
	Vector B3 = Vector (b[0], b[1], b[2] + 0.22);
	Vector B4 = Vector (c[0], c[1], c[2] + 0.22);

	PrismQuad(a, b, c, d, 0.02).Render();
	PrismQuad(A1, F1, F1S, A2, 0.2).Render();
	PrismQuad(F2, B1, B2, F2S, 0.2).Render();
	PrismQuad(A3, B3, B4, A4, 0.03).Render();
}

// ============================================== //
// =================== SQUARE =================== //
// ============================================== //

void Square::Garden()
{
	Quadrangle wall2 = Quadrangle(p[0], p[1], p[2], p[3]).Shrink(0.015, 0.015, 0.015, 0.015);
	Vector a = p[0], b = p[1], c = p[2], d = p[3];
	Vector aS = wall2[0], bS = wall2[1], cS = wall2[2], dS = wall2[3];

	PrismQuad(a, b, bS, aS, 0.1).Render();
	PrismQuad(c, d, dS, cS, 0.1).Render();
	PrismQuad(b, c, cS, bS, 0.1).Render();
	PrismQuad(d, a, aS, dS, 0.1).Render();
}

void Square::Place()
{
	Vector pt1, pt2, pt3, pt4;
	double x = (p[0][0] + p[1][0] + p[2][0] + p[3][0]) / 4;
	double y = (p[0][1] + p[1][1] + p[2][1] + p[3][1]) / 4;

	double x1 = x + 0.2, x2 = x - 0.2, y2 = y - 0.2, y1 = y + 0.2;

	Vector c1 = Vector(x2, y2, 0);
	Vector c2 = Vector(x1, y2, 0);
	Vector c3 = Vector(x1, y1, 0);
	Vector c4 = Vector(x2, y1, 0);
	PrismQuad(c1, c2, c3, c4, 0.05).Render();
	double min = std::min(std::min(std::min(Norm(c1 - c2), Norm(c2 - c3)), Norm(c3 - c4)), Norm(c1 - c4));

	/***construction de pyramides****/

	int i = 0;
	while(min >= 0.05)
	{
		Quadrangle socle = Quadrangle(c1, c2, c3, c4).Shrink(0.02, 0.02, 0.02, 0.02);
		
		c1 = socle[0], c2 = socle[1], c3 = socle[2], c4 = socle[3];
		c1[2] = i * 0.05, c2[2] = i *  + 0.05, c3[2] = i * 0.05, c4[2] = i * 0.05;
		
		pt1 = (c1 + c2) / 2;
		pt2 = (c2 + c3) / 2;
		pt3 = (c3 + c4) / 2;
		pt4 = (c4 + c1) / 2;
		
		PrismQuad(pt1, pt2, pt3, pt4, 0.05).Render();
		c1 = pt1, c2 = pt2, c3 = pt3, c4 = pt4;
		min = std::min(std::min(std::min(Norm(c1 - c2), Norm(c2 - c3)), Norm(c3 - c4)), Norm(c1 - c4));
		
		i++;
	}
}

